package system

import (
	"encoding/json"
	"project-info/src/handle/response"
	"project-info/src/lib"
	"project-info/src/model"
	"project-info/src/service"
	"strconv"

	"gorm.io/gorm"
)

type Meta struct {
	RoleList []uint64 `json:"roleList"`
}

var UserService = &service.UserService{}

func GetMenu(c *lib.GinContext) error {
	jsonMenu := `{
  "code": 0,
  "type": "adminMenu",
  "data": [
    {
      "path": "/home",
      "name": "home",
      "component": "home/index",
      "meta": {
        "title": "message.router.home",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": true,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-shouye"
      }
    },
    {
      "path": "/system",
      "name": "system",
      "component": "layout/routerView/parent",
      "redirect": "/system/menu",
      "meta": {
        "title": "message.router.system",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin"],
        "icon": "iconfont icon-xitongshezhi"
      },
      "children": [
        {
          "path": "/system/menu",
          "name": "systemMenu",
          "component": "system/menu/index",
          "meta": {
            "title": "message.router.systemMenu",
            "isLink": "",
            "isHide": false,
            "isKeepAlive": true,
            "isAffix": false,
            "isIframe": false,
            "roles": ["admin"],
            "icon": "iconfont icon-caidan"
          }
        },
        {
          "path": "/system/user",
          "name": "systemUser",
          "component": "system/user/index",
          "meta": {
            "title": "message.router.systemUser",
            "isLink": "",
            "isHide": false,
            "isKeepAlive": true,
            "isAffix": false,
            "isIframe": false,
            "roles": ["admin"],
            "icon": "iconfont icon-icon-"
          }
        }
      ]
    },
    {
      "path": "/limits",
      "name": "limits",
      "component": "layout/routerView/parent",
      "redirect": "/limits/frontEnd",
      "meta": {
        "title": "message.router.limits",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-quanxian"
      },
      "children": [
        {
          "path": "/limits/backEnd",
          "name": "limitsBackEnd",
          "component": "layout/routerView/parent",
          "meta": {
            "title": "message.router.limitsBackEnd",
            "isLink": "",
            "isHide": false,
            "isKeepAlive": true,
            "isAffix": false,
            "isIframe": false,
            "roles": ["admin", "common"]
          },
          "children": [
            {
              "path": "/limits/backEnd/page",
              "name": "limitsBackEndEndPage",
              "component": "limits/backEnd/page/index",
              "meta": {
                "title": "message.router.limitsBackEndEndPage",
                "isLink": "",
                "isHide": false,
                "isKeepAlive": true,
                "isAffix": false,
                "isIframe": false,
                "roles": ["admin", "common"]
              }
            }
          ]
        }
      ]
    },
    {
      "path": "/menu",
      "name": "menu",
      "component": "layout/routerView/parent",
      "redirect": "/menu/menu1",
      "meta": {
        "title": "message.router.menu",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-caidan"
      },
      "children": [
        {
          "path": "/menu/menu1",
          "name": "menu1",
          "component": "layout/routerView/parent",
          "redirect": "/menu/menu1/menu11",
          "meta": {
            "title": "message.router.menu1",
            "isLink": "",
            "isHide": false,
            "isKeepAlive": true,
            "isAffix": false,
            "isIframe": false,
            "roles": ["admin", "common"],
            "icon": "iconfont icon-caidan"
          },
          "children": [
            {
              "path": "/menu/menu1/menu11",
              "name": "menu11",
              "component": "menu/menu1/menu11/index",
              "meta": {
                "title": "message.router.menu11",
                "isLink": "",
                "isHide": false,
                "isKeepAlive": true,
                "isAffix": false,
                "isIframe": false,
                "roles": ["admin", "common"],
                "icon": "iconfont icon-caidan"
              }
            },
            {
              "path": "/menu/menu1/menu12",
              "name": "menu12",
              "component": "layout/routerView/parent",
              "redirect": "/menu/menu1/menu12/menu121",
              "meta": {
                "title": "message.router.menu12",
                "isLink": "",
                "isHide": false,
                "isKeepAlive": true,
                "isAffix": false,
                "isIframe": false,
                "roles": ["admin", "common"],
                "icon": "iconfont icon-caidan"
              },
              "children": [
                {
                  "path": "/menu/menu1/menu12/menu121",
                  "name": "menu121",
                  "component": "menu/menu1/menu12/menu121/index",
                  "meta": {
                    "title": "message.router.menu121",
                    "isLink": "",
                    "isHide": false,
                    "isKeepAlive": true,
                    "isAffix": false,
                    "isIframe": false,
                    "roles": ["admin", "common"],
                    "icon": "iconfont icon-caidan"
                  }
                },
                {
                  "path": "/menu/menu1/menu12/menu122",
                  "name": "menu122",
                  "component": "menu/menu1/menu12/menu122/index",
                  "meta": {
                    "title": "message.router.menu122",
                    "isLink": "",
                    "isHide": false,
                    "isKeepAlive": true,
                    "isAffix": false,
                    "isIframe": false,
                    "roles": ["admin", "common"],
                    "icon": "iconfont icon-caidan"
                  }
                }
              ]
            },
            {
              "path": "/menu/menu1/menu13",
              "name": "menu13",
              "component": "menu/menu1/menu13/index",
              "meta": {
                "title": "message.router.menu13",
                "isLink": "",
                "isHide": false,
                "isKeepAlive": true,
                "isAffix": false,
                "isIframe": false,
                "roles": ["admin", "common"],
                "icon": "iconfont icon-caidan"
              }
            }
          ]
        },
        {
          "path": "/menu/menu2",
          "name": "menu2",
          "component": "menu/menu2/index",
          "meta": {
            "title": "message.router.menu2",
            "isLink": "",
            "isHide": false,
            "isKeepAlive": true,
            "isAffix": false,
            "isIframe": false,
            "roles": ["admin", "common"],
            "icon": "iconfont icon-caidan"
          }
        }
      ]
    },
    {
      "path": "/fun",
      "name": "funIndex",
      "component": "layout/routerView/parent",
      "redirect": "/fun/tagsView",
      "meta": {
        "title": "message.router.funIndex",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-crew_feature"
      },
      "children": [
        {
          "path": "/fun/tagsView",
          "name": "funTagsView",
          "component": "fun/tagsView/index",
          "meta": {
            "title": "message.router.funTagsView",
            "isLink": "",
            "isHide": false,
            "isKeepAlive": true,
            "isAffix": false,
            "isIframe": false,
            "roles": ["admin", "common"],
            "icon": "ele-Pointer"
          }
        }
      ]
    },
    {
      "path": "/chart",
      "name": "chartIndex",
      "component": "chart/index",
      "meta": {
        "title": "message.router.chartIndex",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-ico_shuju"
      }
    },
    {
      "path": "/personal",
      "name": "personal",
      "component": "personal/index",
      "meta": {
        "title": "message.router.personal",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-gerenzhongxin"
      }
    },
    {
      "path": "/tools",
      "name": "tools",
      "component": "tools/index",
      "meta": {
        "title": "message.router.tools",
        "isLink": "",
        "isHide": false,
        "isKeepAlive": true,
        "isAffix": false,
        "isIframe": false,
        "roles": ["admin", "common"],
        "icon": "iconfont icon-gongju"
      }
    }
  ]
}
`
	m := make(map[string]interface{})
	err := json.Unmarshal([]byte(jsonMenu), &m)
	if err != nil {
		return response.JsonFail(c, err.Error())
	}
	return c.JSON(0, m)
}

// GetMenuList 获取菜单列表
func GetMenuList(c *lib.GinContext) error {
	token := lib.JwtParse(c)
	db := model.DB()

	isAdmin, err := UserService.IsAdmin(token)
	if err != nil {
		return response.JsonFail(c, "查询权限信息出错")
	}

	if !isAdmin {
		menuIds, err := getMenuIdsByUserName(token.UserName)
		if err != nil {
			return response.JsonFail(c, "查询菜单信息出错")
		}
		db = db.Where("id in (?)", menuIds)
	}

	var menuList []*model.Menu
	err = db.Where("type = ? and deleted = 0", model.MenuTypeMenu).Order("parent_id,menu_sort ASC").Find(&menuList).Error
	if err != nil {
		model.GloLogger.Error(err)
		return response.JsonFail(c, "查询菜单列表出错")
	}

	menuMap := make(map[uint64]*model.Menu)
	for _, menu := range menuList {
		if menu.Type == model.MenuTypeMenu {
			menuMap[menu.Id] = menu
		}
	}

	tree := make([]*model.Menu, 0)
	for _, menu := range menuList {
		if menu.Type == model.MenuTypeButton {
			continue
		}
		parentID := menu.ParentId
		if parentID == 0 {
			tree = append(tree, menu)
		} else {
			parent, ok := menuMap[parentID]
			if ok {
				parent.Children = append(parent.Children, menu)
			}
		}
	}

	return response.JsonOk(c, tree, "success")
}

func getMenuIdsByUserName(username string) ([]uint64, error) {
	var menuIds []uint64
	user, err := getUserByUserName(username)
	if err != nil {
		model.GloLogger.Error(err)
		return menuIds, err
	}
	err = model.DB().Model(&model.MenuRole{}).Select("menu_id").
		Joins("JOIN role_users ON role_users.role_id = menu_roles.role_id").
		Where("role_users.user_id = ?", user.Id).Find(&menuIds).Error
	return menuIds, err
}

func getRoleMenuIds(userRoleIds []uint64) ([]uint64, error) {
	var roleMenuIds []uint64
	err := model.DB().Model(&model.MenuRole{}).Select("menu_id").Where("role_id in (?)", userRoleIds).Find(&roleMenuIds).Error
	return roleMenuIds, err
}

func getUserByUserName(username string) (model.User, error) {
	var user model.User
	err := model.DB().Where("username = ?", username).First(&user).Error
	return user, err
}

func getRoleIdsByUserId(user model.User) ([]uint64, error) {
	var roleIds []uint64
	err := model.DB().Model(&model.RoleUser{}).Select("role_id").Where("user_id = ?", user.Id).Find(&roleIds).Error
	return roleIds, err
}

// AddMenu 添加菜单
func AddMenu(c *lib.GinContext) error {
	var menu model.Menu
	err := c.Bind(&menu)
	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, err.Error())
	}

	var meta Meta
	err = json.Unmarshal([]byte(menu.Meta), &meta)
	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, err.Error())
	}
	model.DB().Transaction(func(tx *gorm.DB) error {
		if menu.IsCreate() {
			err = tx.Create(&menu).Error
		} else {
			err = tx.Save(&menu).Error
		}
		if err != nil {
			return err
		}
		err = tx.Where("menu_id = ?", menu.Id).Delete(&model.MenuRole{}).Error
		if err != nil {
			return err
		}
		if meta.RoleList != nil {
			var menuRoles []*model.MenuRole
			for _, id := range meta.RoleList {
				menuRoles = append(menuRoles, &model.MenuRole{
					MenuId: menu.Id,
					RoleId: id,
				})
			}
			if len(menuRoles) > 0 {
				return tx.Create(&menuRoles).Error
			}
		}
		return nil
	})
	return response.JsonOk(c, menu, "success")
}

// DeleteMenu 删除菜单
func DeleteMenu(c *lib.GinContext) error {
	menuIdP := c.QueryParam("id")
	menuId, err := strconv.ParseUint(menuIdP, 10, 64)
	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, err.Error())
	}

	err = model.DB().Transaction(func(tx *gorm.DB) error {
		err = tx.Where("id = ?", menuId).Delete(&model.Menu{}).Error
		if err != nil {
			return err
		}
		err = tx.Where("menu_id = ?", menuId).Delete(&model.MenuRole{}).Error
		if err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, err.Error())
	}
	return response.JsonOk(c, nil, "success")
}

// TreeMenu 获取菜单树
func TreeMenu(c *lib.GinContext) error {
	var menuList []*model.Menu
	err := model.DB().Where("deleted = 0").Order("parent_id,menu_sort ASC").Find(&menuList).Error

	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, err.Error())
	}

	menuMap := make(map[uint64]*model.Menu)
	for _, menu := range menuList {
		if menu.Type == model.MenuTypeButton {
			menu.Children = nil
		} else {
			menu.Children = make([]*model.Menu, 0)
		}

		menuMap[menu.Id] = menu
	}

	tree := make([]*model.Menu, 0)
	for _, menu := range menuList {
		parentID := menu.ParentId
		if parentID == 0 {
			tree = append(tree, menu)
		} else {
			parent, ok := menuMap[parentID]
			if ok {
				parent.Children = append(parent.Children, menu)
			}
		}
	}

	return response.JsonOk(c, tree, "success")
}

// getMenuRolesMap 获取菜单角色map
func getMenuRolesMap() map[uint64][]uint64 {
	var menuRoles []model.MenuRole
	model.DB().Find(&menuRoles)
	menuRoleMap := make(map[uint64][]uint64)
	for _, menuRole := range menuRoles {
		menuRoleMap[menuRole.MenuId] = append(menuRoleMap[menuRole.MenuId], menuRole.RoleId)
	}
	return menuRoleMap
}
